// 为了理解约束泛型，先走下面的例子
function transfer<T>(param: T): T {
  /*
    * 这里ts语法检查会报错
    * 原因是：语句中已经认为param拥有length属性， 但实际上却不一定有
    * 因为不能确定param会被传什么类型
  */
  // console.log(param.length);
  return param;
}

// 为了解决上一问题，我们可以给泛型加上描述, 意思是说传入一个任意类型的数组
function advance<T>(param: T[]): T[] {
  console.log(param.length);
  return param;
}

/*
  * 但是另一个问题也随之到来
  * string, obj类型的数据也会拥有length属性，只定义数组不灵活且容易出现错误
  * 约束泛型，随之到来
  * T extends IWithLength => T继承IWithLength 那么T就必须拥有length属性
*/
interface IWithLength {
  length: number;
}
function distant<T extends IWithLength>(param: T): T {
  console.log(param.length);
  return param;
}

const data = distant([1, 2, '3']);
const data1 = distant('123');
const data2 = distant({ length: 123 });
console.log(data);
console.log(data1);
console.log(data2);